<script lang="ts" name="ProTable" setup>
import { ColumnsTypes } from './types'
import { Refresh } from '@element-plus/icons-vue'
import { titleCase } from '@/utils'
import { useProTable } from './hooks/useProTable'
import { ProTableState } from './injectKey'

/** 定义父组件传过来参数的类型 */
interface ProTypeProps {
  columns: ColumnsTypes[] // 查询、列表、表单配置项
  request: (params: any) => Promise<any> // 表格数据API ===> 必传
  isSearch?: boolean // 是否显示查询 ===> 非必传，默认显示（true）
  isPage?: boolean // 是否显示分页 ===> 非必传，默认显示（true）
  span?: number // 查询表单布局 ===> 非必传，默认为 6
  rowKey?: string // 表格的Key ===> 非必传
  dataKey?: string // 表格响应列表数据的`key`值 ===> 非必传， 默认值 ==> data
  isTreeData?: boolean // 表格列表数据是否为树结构 ===> 非必传，默认列表数据（false）
}

/** 配置父组件传过来参数的默认值 */
const props = withDefaults(defineProps<ProTypeProps>(), {
  columns: () => [],
  isSearch: true,
  isPage: true,
  span: 6,
  rowKey: 'id',
  dataKey: 'data',
  isTreeData: false
})

const {
  searchColumns,
  searchModel,
  settingColumns,
  tableColumns,
  tableData,
  pageSizes,
  pagination,
  initSearch,
  initTable,
  search,
  reset,
  watchTableColumns,
  handleSizeChange,
  handleCurrentChange
} = useProTable(
  props.request,
  props.dataKey,
  props.columns,
  'menuId',
  props.isTreeData
)

watch(
  () => settingColumns.value,
  () => {
    watchTableColumns()
  },
  { deep: true }
)

onMounted(() => {
  initSearch()
  initTable()
  search()
  watchTableColumns()
})

provide(ProTableState, {
  tableColumns: settingColumns
})

defineExpose({
  search
})
</script>

<template>
  <div class="table_card el-card">
    <!-- 查询模块 -->
    <Search
      v-if="props.isSearch"
      v-model:search-model="searchModel"
      :search-columns="searchColumns"
      :span="span"
      :search="search"
      :reset="reset"
    />
    <!-- 表格头部按钮栏 -->
    <div class="table_header title_bar flex jfe">
      <div class="header_btns">
        <slot name="tableHeader" />
      </div>
      <div class="site_btns">
        <el-button :icon="Refresh" circle @click="search" />
        <TableSetting />
      </div>
    </div>

    <!-- 表格模块 -->
    <el-table
      ref="tableRef"
      height="600"
      class="table_main"
      style="width: 100%"
      :data="tableData"
      :row-key="rowKey"
    >
      <template v-if="tableColumns?.length">
        <template v-for="col in tableColumns" :key="col.prop!">
          <el-table-column
            v-if="col.colType === 'selection'"
            v-bind="col.attrs"
            :type="col.colType"
            :label="col.label"
            reserve-selection
          />
          <el-table-column
            v-else-if="col.colType === 'expand'"
            v-slot="scope"
            v-bind="col.attrs"
            :type="col.colType"
            :label="col.label"
          >
            <slot :name="`table${titleCase(col.prop!)}`" :row="scope.row" />
          </el-table-column>
          <el-table-column
            v-else
            v-bind="col.attrs"
            :prop="col.prop"
            :label="col.label"
            resizable
          >
            <!-- 自定义头部内容(tsx) -->
            <template v-if="col.renderTableHeader" #header>
              <component :is="col.renderTableHeader" :row="col" />
            </template>

            <template #default="scope">
              <slot :name="`table${titleCase(col.prop!)}`" :row="scope.row">
                <span>{{ scope.row[col.prop!] }}</span>
              </slot>
            </template>
          </el-table-column>
        </template>
      </template>
      <template #empty>
        <el-empty description="暂无数据" />
      </template>
    </el-table>

    <!-- 分页模块 -->
    <template v-if="isPage">
      <el-pagination
        v-model:currentPage="pagination.current"
        v-model:page-size="pagination.size"
        class="page_box flex jfe"
        layout="total, sizes, prev, pager, next, jumper"
        background
        :page-sizes="pageSizes"
        :total="pagination.total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </template>
  </div>
</template>

<style lang="less" scoped>
.table_card {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 20px;
  display: flex;
  flex-direction: column;

  .table_header {
    width: 100%;
    padding: 0 0 20px;
    box-sizing: border-box;

    .site_btns {
      margin-left: 20px;
    }
  }

  .table_main {
    flex: 1;

    :deep(.el-table__inner-wrapper) {
      height: 100% !important;
    }

    :deep(.el-table__header) {
      .cell {
        font-weight: 400;
        color: var(--el-text-color-regular);
      }
    }
  }

  .page_box {
    width: 100%;
    margin-top: 20px;
    box-sizing: border-box;
  }
}
</style>
